package util.input;

import util.core.Periodic;

import java.util.ArrayList;

public class InputFixer {
    boolean[] validLetters;
    String molecule;
    String original;
    boolean[] changed, single;
    int[] values;


    public InputFixer(String c) {
        original = c;
        validLetters = getLetters(c);
        molecule = c.toUpperCase();
        changed = new boolean[c.length() + 1];
    }

    private boolean[] getLetters(String c) {
        boolean[] letters = new boolean[c.length()];
        for (int i = 0; i < c.length(); i++) {
            if (Parser.isLetter(c.charAt(i))) {
                letters[i] = true;
            }
        }
        return letters;
    }

    private void fix() {
        if (molecule.length() == 0) {
            return;
        }
        if (molecule.length() == 1) {
            changed[0] = true;
            return;
        }

        values = new int[molecule.length()];
        single = new boolean[molecule.length()];
        int action = 1;
        while (action != 0) {
            action = 0;
            count(values, single);
            for (int i = 0; i < molecule.length() - 1; i++) {
                int val1 = values[i];
                int val2 = values[i + 1];
                if (validLetters[i]) {
                    if (val2 == 0 && (dependent(i))) {
                        validLetters[i] = false;
                        changed[i] = true;
                        changed[i + 1] = true;
                        lower(i + 1);
                        validLetters[i + 1] = false;
                        values[i + 1] = 0;
                        values[i] = 0;
                        action++;
                    } else if (single[i] && values[i] == 1 && !(i != 0 && dependent(i - 1))) {
                        validLetters[i] = false;
                        changed[i] = true;
                        values[i] = 0;
                        action++;
                    } else if (i >= 1 && !single[i] && values[i] == 1 && values[i + 1] == 0) {
                        if (!validLetters[i - 1]) {
                            validLetters[i] = false;
                            validLetters[i + 1] = false;
                            changed[i] = true;
                            changed[i + 1] = true;
                            lower(i + 1);
                            values[i + 1] = 0;
                            values[i] = 0;
                            action++;
                        }
                    } else if (i == 0 && values[i] == 1) {
                        validLetters[i] = false;
                        validLetters[i + 1] = false;
                        changed[i] = true;
                        changed[i + 1] = true;
                        lower(i + 1);
                        values[i + 1] = 0;
                        values[i] = 0;
                        action++;
                    }
                }
            }
        }
    }

    private boolean dependent(int i) {
        return (values[i] == 1 && !single[i]) || values[i] == 2;
    }

    public void fix1() {
        fix();
        merge();
    }

    private void merge() {
        String merge = "";
        for (int i = 0; i < molecule.length(); i++) {
            if (changed[i] || (i > 0 && i == molecule.length() - 1 && !changed[i] && !(values[i - 1] == 2 || (values[i - 1] == 1 && !single[i - 1])))) {
                merge += molecule.charAt(i);
            } else {
                merge += original.charAt(i);
            }
        }
        molecule = merge;
    }

    private void lower(int index) {
        molecule = molecule.substring(0, index) + molecule.substring(index, index + 1).toLowerCase() + molecule.substring(index + 1);
    }

    private void count(int[] values, boolean[] single) {
        clear(values);
        for (int i = 0; i < molecule.length(); i++) {
            String cur = molecule.substring(i, i + 1);
            ArrayList<String> stuff = Periodic.getElementNamesWith(cur);
            String next = nextLetter(i + 1);
            if (validLetters[i]) {
                if (next != null && validLetters[i + 1]) {
                    if (stuff.contains(cur + next.toLowerCase()))
                        values[i]++;
                }
                if (stuff.contains(cur)) {
                    values[i]++;
                    single[i] = true;
                }
            }
        }
    }

    private void clear(int[] array) {
        for (int i = 0; i < array.length; i++) {
            array[i] = 0;
        }
    }


    private String nextLetter(int start) {
        if (start == molecule.length())
            return null;
        if (Parser.isLetter(molecule.charAt(start)))
            return molecule.substring(start, start + 1);
        return null;
    }

    public String getResult() {
        return molecule;
    }


}
